using Microsoft.Extensions.Logging;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using SumerCoreDevOps.Shared.Enums;
using SumerCoreDevOps.Shared.Constants;

namespace SumerCoreDevOps.Infrastructure.Security;

/// <summary>
/// 凭证管理器
/// </summary>
public class CredentialManager
{
    private readonly ILogger<CredentialManager> _logger;
    private readonly byte[] _masterKey;
    private readonly Dictionary<long, TempCredential> _tempCredentials = new();
    private readonly object _lock = new();

    public CredentialManager(ILogger<CredentialManager> logger, string masterKey)
    {
        _logger = logger;
        _masterKey = SHA256.HashData(Encoding.UTF8.GetBytes(masterKey));

        // 启动过期凭证清理任务
        _ = Task.Run(CleanupExpiredCredentialsAsync);
    }

    /// <summary>
    /// 生成临时凭证
    /// </summary>
    public string GenerateTempCredential(
        long taskId,
        CredentialType credentialType,
        object credentialData,
        int validMinutes = TcpProtocolConstants.TempCredentialValidMinutes)
    {
        var credential = new TempCredential
        {
            TaskId = taskId,
            CredentialType = credentialType,
            Data = credentialData,
            ExpiresAt = DateTime.UtcNow.AddMinutes(validMinutes),
            Token = GenerateToken()
        };

        lock (_lock)
        {
            _tempCredentials[taskId] = credential;
        }

        // 加密凭证数据
        var jsonData = JsonSerializer.Serialize(credentialData);
        var encryptedData = EncryptCredential(jsonData);

        _logger.LogInformation("生成临时凭证: TaskId={TaskId}, Type={Type}, ExpiresAt={ExpiresAt}",
            taskId, credentialType, credential.ExpiresAt);

        return encryptedData;
    }

    /// <summary>
    /// 验证并解密凭证
    /// </summary>
    public (bool IsValid, T? Data) ValidateAndDecryptCredential<T>(long taskId, string encryptedCredential)
        where T : class
    {
        lock (_lock)
        {
            if (!_tempCredentials.TryGetValue(taskId, out var credential))
            {
                _logger.LogWarning("凭证不存在: TaskId={TaskId}", taskId);
                return (false, null);
            }

            if (credential.ExpiresAt < DateTime.UtcNow)
            {
                _logger.LogWarning("凭证已过期: TaskId={TaskId}, ExpiresAt={ExpiresAt}",
                    taskId, credential.ExpiresAt);
                _tempCredentials.Remove(taskId);
                return (false, null);
            }

            try
            {
                var decryptedJson = DecryptCredential(encryptedCredential);
                var data = JsonSerializer.Deserialize<T>(decryptedJson);
                return (true, data);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "解密凭证失败: TaskId={TaskId}", taskId);
                return (false, null);
            }
        }
    }

    /// <summary>
    /// 撤销凭证
    /// </summary>
    public void RevokeCredential(long taskId)
    {
        lock (_lock)
        {
            if (_tempCredentials.Remove(taskId))
            {
                _logger.LogInformation("撤销凭证: TaskId={TaskId}", taskId);
            }
        }
    }

    /// <summary>
    /// 加密凭证
    /// </summary>
    private string EncryptCredential(string plainText)
    {
        using var aes = Aes.Create();
        aes.Key = _masterKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.GenerateIV();

        using var encryptor = aes.CreateEncryptor();
        var plainBytes = Encoding.UTF8.GetBytes(plainText);
        var encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);

        // IV + 加密数据
        var result = new byte[aes.IV.Length + encryptedBytes.Length];
        Buffer.BlockCopy(aes.IV, 0, result, 0, aes.IV.Length);
        Buffer.BlockCopy(encryptedBytes, 0, result, aes.IV.Length, encryptedBytes.Length);

        return Convert.ToBase64String(result);
    }

    /// <summary>
    /// 解密凭证
    /// </summary>
    private string DecryptCredential(string encryptedText)
    {
        var encryptedBytes = Convert.FromBase64String(encryptedText);

        using var aes = Aes.Create();
        aes.Key = _masterKey;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;

        // 提取 IV
        var iv = new byte[16];
        Buffer.BlockCopy(encryptedBytes, 0, iv, 0, 16);
        aes.IV = iv;

        using var decryptor = aes.CreateDecryptor();
        var decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 16, encryptedBytes.Length - 16);

        return Encoding.UTF8.GetString(decryptedBytes);
    }

    /// <summary>
    /// 生成令牌
    /// </summary>
    private string GenerateToken()
    {
        var bytes = new byte[32];
        using var rng = RandomNumberGenerator.Create();
        rng.GetBytes(bytes);
        return Convert.ToBase64String(bytes);
    }

    /// <summary>
    /// 清理过期凭证
    /// </summary>
    private async Task CleanupExpiredCredentialsAsync()
    {
        while (true)
        {
            try
            {
                await Task.Delay(TimeSpan.FromMinutes(1));

                lock (_lock)
                {
                    var now = DateTime.UtcNow;
                    var expiredTasks = _tempCredentials
                        .Where(kv => kv.Value.ExpiresAt < now)
                        .Select(kv => kv.Key)
                        .ToList();

                    foreach (var taskId in expiredTasks)
                    {
                        _tempCredentials.Remove(taskId);
                        _logger.LogDebug("清理过期凭证: TaskId={TaskId}", taskId);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理过期凭证任务异常");
            }
        }
    }
}

/// <summary>
/// 临时凭证
/// </summary>
internal class TempCredential
{
    public long TaskId { get; set; }
    public CredentialType CredentialType { get; set; }
    public object Data { get; set; } = null!;
    public DateTime ExpiresAt { get; set; }
    public string Token { get; set; } = null!;
}

/// <summary>
/// Git凭证
/// </summary>
public class GitCredential
{
    public string Username { get; set; } = null!;
    public string Password { get; set; } = null!;
    public string? Token { get; set; }
}

/// <summary>
/// Docker凭证
/// </summary>
public class DockerCredential
{
    public string Registry { get; set; } = null!;
    public string Username { get; set; } = null!;
    public string Password { get; set; } = null!;
}

/// <summary>
/// Kubernetes凭证
/// </summary>
public class KubernetesCredential
{
    public string ClusterUrl { get; set; } = null!;
    public string? Token { get; set; }
    public string? KubeConfig { get; set; }
    public string Namespace { get; set; } = "default";
}

/// <summary>
/// Maven凭证
/// </summary>
public class MavenCredential
{
    public string RepositoryUrl { get; set; } = null!;
    public string Username { get; set; } = null!;
    public string Password { get; set; } = null!;
}

/// <summary>
/// NuGet凭证
/// </summary>
public class NuGetCredential
{
    public string Source { get; set; } = null!;
    public string ApiKey { get; set; } = null!;
}
